package com.base.pub.mapper;

import java.io.IOException;

import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;

/**
 * 
 *  Class Name: SimpleJsonMapper.java
 *  Description: 
 *  @DateTime 2013年1月23日 
 *  @version 1.0
 */
public class SimpleJsonMapper extends ObjectMapper {
	
	private static Logger logger = LoggerFactory.getLogger(SimpleJsonMapper.class);
	private static SimpleJsonMapper jsonMapper;
	
	public SimpleJsonMapper() {
		init();
	}

	public SimpleJsonMapper(Include include) {
		if (include != null) {
			this.setSerializationInclusion(include);
		}
		
		this.init();
		
	}
	
	public static SimpleJsonMapper getInstance() {
		if (jsonMapper == null) {
			synchronized (SimpleJsonMapper.class) {
				jsonMapper = new SimpleJsonMapper();
			}
		}
		return jsonMapper;
	}
	
	public String toJson(Object value) {
		try {
			return this.writeValueAsString(value);
		}catch(JsonProcessingException e) {
			return null;
		}
	}
	
	public <T> T fromJson(String jsonString, JavaType javaType) {
		if (StringUtils.isEmpty(jsonString)) {
			return null;
		}
		try {
			return (T) this.readValue(jsonString, javaType);
		} catch (IOException e) {
			return null;
		}
	}
	
	public JavaType constructCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
		return this.getTypeFactory().constructParametricType(collectionClass, elementClasses);
	}
	
	public SimpleJsonMapper enableEnumUseToString() {
		this.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
		this.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING);
		return this;
	}
	
	public SimpleJsonMapper enableJaxbAnnotation() {
		JaxbAnnotationModule module = new JaxbAnnotationModule();
		this.registerModule(module);
		return this;
	}
	
	public <T> T fromJson(String value, Class<T> type) {
		if (StringUtils.isEmpty(value)) {
			return null;
		}
		try {
			return this.readValue(value, type);
		}catch(IOException e) {
			return null;
		}
	}
	
	public static String toJsonStr(Object value) {
		return jsonMapper.toJson(value);
	}
	
	private void init() {
		this.configure(Feature.ALLOW_SINGLE_QUOTES, true);
		this.configure(Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
		
		this.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
		
		this.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
			
			@Override
			public void serialize(Object value, JsonGenerator gen,SerializerProvider provider) 
							throws IOException, JsonProcessingException {
				gen.writeString("");
			}
		});
		
		this.registerModule(new SimpleModule().addSerializer(String.class, new JsonSerializer<String>() {
			@Override
			public void serialize(String value, JsonGenerator gen,SerializerProvider provider) 
					throws IOException, JsonProcessingException {
				gen.writeString(StringEscapeUtils.escapeHtml4(value));
			}
		}));
		
		
	}
}
